package jcu.sal.agent.netty;

import jcu.sal.agent.NettyAgentImpl;
import jcu.sal.common.StreamID;
import jcu.sal.common.CommandFactory.Command;
import jcu.sal.common.agents.netty.NettyConstants;
import jcu.sal.common.agents.netty.NettyMessage;
import jcu.sal.common.exceptions.ConfigurationException;
import jcu.sal.common.exceptions.NotFoundException;
import jcu.sal.common.exceptions.SALDocumentException;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

/**
 * @author Marc Hammerton
 * 
 */
@ChannelPipelineCoverage("all")
public class NettyAgentHandler extends SimpleChannelHandler {

	private NettyAgentImpl agent;

	public NettyAgentHandler(NettyAgentImpl agent) {
		this.agent = agent;
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		System.out
				.println("Agent Exception: " + ctx.getPipeline().getChannel());
		String exception = e.getCause().toString();
		if (exception.contains("Connection reset by peer")) {
			agent.unregisterClient(e.getChannel());
		} else {
//			e.getCause().printStackTrace();
			 System.out.println(e.getCause());
		}
	}

	@Override
	public void messageReceived(ChannelHandlerContext chx, MessageEvent e) {

		NettyMessage message = (NettyMessage) e.getMessage();

		String response = null;
		switch (message.getType()) {
			case NettyConstants.REQ_REGISTER:
				try {
					agent.registerClient((String) message.getData(0), e
							.getChannel());
				} catch (ConfigurationException e1) {
					e1.printStackTrace();
				}
				e.getChannel().write("done");
				break;
			case NettyConstants.REQ_UNREGISTER:
				try {
					agent.unregisterClient(e.getChannel());
				} catch (ConfigurationException e1) {
					e1.printStackTrace();
				}
				e.getChannel().write("done");
				break;
			case NettyConstants.REQ_ADD_PROTOCOL:
				System.out.println("Message received for addProtocol: "
						+ (String) message.getData(1) + " - "
						+ (Boolean) message.getData(0));
				try {
					agent.addProtocol((String) message.getData(1),
							(Boolean) message.getData(0));
				} catch (SALDocumentException e1) {
					e1.printStackTrace();
				} catch (ConfigurationException e1) {
					e1.printStackTrace();
				}
				break;
			case NettyConstants.REQ_ADD_SENSOR:
				try {
					response = agent.addSensor((String) message.getData(0));
				} catch (SALDocumentException e1) {
					e1.printStackTrace();
				} catch (ConfigurationException e1) {
					e1.printStackTrace();
				}
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_GET_CML:
				try {
					response = agent.getCML((String) message.getData(0));
				} catch (NotFoundException e1) {
					e1.printStackTrace();
				}
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_GET_ID:
				response = agent.getID();
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_GET_TYPE:
				response = agent.getType();
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_LIST_ACTIVE_SENSORS:
				response = agent.listActiveSensors();
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_LIST_PROTOCOLS:
				response = agent.listProtocols();
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_LIST_SENSOR:
				try {
					response = agent.listSensor((String) message.getData(0));
				} catch (NotFoundException e1) {
					e1.printStackTrace();
				}
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_LIST_SENSORS:
				response = agent.listSensors();
				e.getChannel().write(response);
				break;
			case NettyConstants.REQ_REMOVE_PROTOCOL:
				try {
					agent.removeProtocol((String) message.getData(1),
							(Boolean) message.getData(0));
				} catch (NotFoundException e1) {
					e1.printStackTrace();
				}
				break;
			case NettyConstants.REQ_REMOVE_SENSOR:
				try {
					agent.removeSensor((String) message.getData(0));
				} catch (NotFoundException e1) {
					e1.printStackTrace();
				}
				break;
			case NettyConstants.REQ_SETUP_STREAM:
				StreamID id = agent.setupStream(e.getChannel(),
						(Command) message.getData(0), (String) message
								.getData(1));
				if (id != null) {
					e.getChannel().write(id);
				} else {
					e.getChannel().write("null");
				}
				break;
			case NettyConstants.REQ_START_STREAM:
				try {
					agent.startStream((StreamID) message.getData(0));
				} catch (NotFoundException e1) {
					e1.printStackTrace();
				}
				break;
			case NettyConstants.REQ_TERMINATE_STREAM:
				try {
					agent.terminateStream((StreamID) message.getData(0));
				} catch (NotFoundException e1) {
					e1.printStackTrace();
				}
				break;
			case NettyConstants.REQ_REG_EVENTHANDLER:
				agent.registerEventHandler(e.getChannel(), (String) message
						.getData(0));
				e.getChannel().write("done");
				break;
			case NettyConstants.REQ_UNREG_EVENTHANDLER:
				agent.unregisterEventHandler(e.getChannel(), (String) message
						.getData(0));
				e.getChannel().write("done");
				break;
			default:
				System.out.println("No known message type: "
						+ e.getMessage().toString());
				break;
		}

	}
}
